#!/usr/bin/env python
from google.appengine.ext import db
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext.webapp import template
import os, uuid
from google.appengine.ext.webapp.util import login_required

def RequiresLogin(fun):
	def RequiresLoginDecorator(self, *args, **kwargs):
		if not self.user:
			self.redirect(users.create_login_url("/control_panel"))
			return
		return fun(self, *args, **kwargs)
	return RequiresLoginDecorator

class Website(db.Model):
	''' Stores API Access for a Google Account. '''
	user = db.UserProperty()
	domain = db.StringProperty()
	active = db.BooleanProperty()
	apikey = db.StringProperty()
	secret = db.StringProperty()

class InfoRecord(db.Model):
	website = db.ReferenceProperty(Website)
	identifier = db.StringProperty()
	storage = db.StringProperty()

def db_create_website( user, domain ):
	''' create a new Website '''

	apikey = str( uuid.uuid4() ).replace('-', '')
	while db.GqlQuery("SELECT * FROM Website WHERE apikey = :1", apikey).get():
		apikey = str( uuid.uuid4() ).replace('-', '')

	secret = str( uuid.uuid4() ).replace('-', '')
	while db.GqlQuery("SELECT * FROM Website WHERE secret = :1", secret).get():
		secret = str( uuid.uuid4() ).replace('-', '')

	return Website(
			user = user,
			domain = domain,
			apikey = apikey,
			secret = secret,
			active = True
		).put()

class RequestHandler(webapp.RequestHandler):
	def initialize(self, request, response):
		super(RequestHandler, self).initialize(request, response)
		self.user = users.get_current_user()
    
	def var(self, key, default = None):
		return self.request.get( key, default )

	def template(self, f, vars = {}):
		user = self.user
		if user is not None:
			websites = []
			for website in Website.all().filter('user', user):
				websites.append( website )

			vars['user'] = user.nickname()
			vars['websites'] = websites
			vars['user_email'] = user.email()
			vars['logout'] = users.create_logout_url('/')
		else:
			vars['login'] = users.create_login_url('/control_panel')

		path = os.path.join(os.path.dirname(__file__), 'templates', f + '.html')
		self.response.out.write( template.render(path, vars) )

	def to(self, path, **extra_params):
		if '://' in path:
			from urlparse import urlparse
			o = urlparse(path)
			path = o.path
		params = {}

		temp = path.split('?')
		if len( temp ) > 1:
			path = temp.pop(0)
			temp = '?'.join(temp)

			for temp in temp.split('&'):
				(key, value) = temp.split('=')
				params[ key ] = value

		params.update(extra_params)

		scheme = 'http'
		domain = 'www.killswitch.me'
		if params.get('secure'):
			del params['secure']
			scheme = 'https'
			domain = 'killswitch-me.appspot.com'

		from urllib import urlencode
		return self.redirect( '%s?%s' % ( path, urlencode( params ) ) )
		#return self.redirect( '%s://%s%s?%s' % ( scheme, domain, path, urlencode( params ) ) )

	def write( self, c ):
		self.response.out.write( c )

class home(webapp.RequestHandler):
	''' home page '''
	def get(self):
		vars = {
			'current_home': True,
			#'login': users.create_login_url('/control_panel'),
			}
		user = users.get_current_user()
		if user:
			vars['user'] = user
		path = os.path.join(os.path.dirname(__file__), 'templates', 'home.html')
		self.response.out.write( template.render(path, vars) )
		
class control_panel(RequestHandler):
	''' control panel '''
	@RequiresLogin
	def get(self):
		if self.var('error'):
			self.template( 'control_panel', { 'error': 'Sorry, you already have a website called that.', 'current_control_panel': True } )
		else:
			self.template( 'control_panel', { 'current_control_panel': True } )

class create_website(RequestHandler):
	''' privacy policy '''
	@RequiresLogin
	def get(self):
		website = Website.all().filter('user', self.user).filter('domain', self.var('domain')).get()
		if website:
			self.to( '/control_panel', error = True)
		else:
			db_create_website( self.user, self.var('domain') )
			self.to( '/control_panel' )

class view_site(RequestHandler):
	''' view inforecords for a Website '''
	@RequiresLogin
	def get(self, key):
		website = Website.get( db.Key( key ) )
		if website.user != self.user: return self.to('/')
		inforecords = []
		for inforecord in InfoRecord.all().filter('website', website):
			inforecords.append( inforecord )
		self.template( 'control_panel', { 'view_site': website.domain, 'inforecords': inforecords, 'website': website } )

class toggle_active(RequestHandler):
	''' toggle the active status of a Website '''
	@RequiresLogin
	def get(self, key):
		website = Website.get( db.Key( key ) )
		if website.user != self.user: return self.to('/')
		if website.active:
			website.active = False
		else:
			website.active = True
		website.put()
		self.to( '/view_site/%s' % website.key() )
		
class delete(RequestHandler):
	''' delete an inforecord '''
	@RequiresLogin
	def get(self, key):
		inforecord = InfoRecord.get( db.Key( key ) )
		website = inforecord.website
		if website.user != self.user: return self.to('/')
		inforecord.delete()
		self.to( '/view_site/%s' % website.key() )

class api_add(RequestHandler):
	''' API: Add or Rename or Update a new InfoRecord '''
	def get(self): self.post()
	def post(self):
		website = Website.all().filter('apikey', self.var('apikey')).filter('secret', self.var('secret')).get()
		if not website:
			self.write('0\napikey or secret are incorrect, could not lookup website.')
		else:
			# Update Identifier
			if self.var('identifier') and self.var('new_identifier') and len(self.var('identifier')) and len(self.var('new_identifier')):
				inforecord = InfoRecord.all().filter('website', website).filter('identifier', self.var('identifier')).get()
				inforecord.identifier = self.var('new_identifier')
				inforecord.put()
				self.write('1')

			# Update Storage
			elif self.var('identifier') and self.var('storage') and len(self.var('identifier')) and len(self.var('storage')):
				inforecord = InfoRecord.all().filter('website', website).filter('identifier', self.var('identifier')).get()
				if inforecord:
					inforecord.storage = self.var('storage')
				else:
					inforecord = InfoRecord( website = website, identifier = self.var('identifier'), storage = self.var('storage') )
				inforecord.put()
				self.write('1')

			# Else
			else:
				self.write('0\nMissing a required param, or a required param is empty.')

class api_check(RequestHandler):
	''' API: Check an InfoRecord '''
	def get(self): self.post()
	def post(self):
		website = Website.all().filter('apikey', self.var('apikey')).filter('secret', self.var('secret')).get()
		if not website:
			self.write('0\napikey or secret are incorrect, could not lookup website.')
		elif not website.active:
			self.write('0\nyou\'ve been shutdown.')
		elif not self.var('identifier') or len(self.var('identifier')) is 0:
			self.write('0\nidentifier is empty or is not set.')
		else:
			inforecord = InfoRecord.all().filter('website', website).filter('identifier', self.var('identifier')).get()
			if not inforecord:
				self.write('0\nDoes not exist.')

			elif inforecord.storage == self.var('storage'):
				self.write('1')

			else:
				self.write('0\nCheck failed.')

class api_delete(RequestHandler):
	''' API: Delete an InfoRecord '''
	def get(self): self.post()
	def post(self):
		website = Website.all().filter('apikey', self.var('apikey')).filter('secret', self.var('secret')).get()
		if not website:
			self.write('0\napikey or secret are incorrect, could not lookup website.')
		elif not self.var('identifier') or len(self.var('identifier')) is 0:
			self.write('0\nidentifier is empty or is not set.')
		else:
			inforecord = InfoRecord.all().filter('website', website).filter('identifier', self.var('identifier')).get()
			if not inforecord:
				self.write('0\nDoes not exist.')
			else:
				inforecord.delete()
				self.write('1')

application = webapp.WSGIApplication([
	# Home Pages
	('/', home),
	('/control_panel', control_panel),
	('/create_website/?', create_website),
	('/view_site/(.*)/?', view_site),
	('/toggle_active/(.*)/?', toggle_active),
	('/delete/(.*)/?', delete),
	('/api/add/?', api_add),
	('/api/rename/?', api_add),
	('/api/update/?', api_add),
	('/api/check/?', api_check),
	('/api/delete/?', api_delete),
	], debug=True)

def main():
	run_wsgi_app(application)

if __name__ == '__main__':
	main()
